#pragma once

#include <memory>
#include <string>
#include <vector>
#include <functional>
#include <QString>
#include <QList>

#include "application/map/map_application_service.h"
#include "application/vehicle/vehicle_service.h"
#include "infrastructure/services/common_service.h"
#include "kernel/agv/agv_entity.h"
#include "kernel/interfaces/IConfiguration.h"
#include "kernel/interfaces/ILogger.h"
#include "kernel/interfaces/Result.h"

namespace application {
namespace dispatcher {

// Forward declaration
class DispatcherManager;

/**
 * @brief 调度结果句柄
 */
struct DispatchResult {
  // 是否成功
  bool success{false};

  // 选中的AGV编号（-1表示未选中）
  int agvNumber{-1};

  // 规划的路径（站点列表）
  std::vector<std::string> path;

  // 错误消息
  std::string errorMessage;

  // 是否需要退出充电
  bool needQuitCharging{false};

  // 是否跨楼层
  bool isCrossFloor{false};
};

/**
 * @brief 调度服务 - 负责AGV调度、路径规划、冲突管理
 * @details 对应三方代码中的 DispatcherManager
 *          Clean Architecture 设计：应用层服务
 */
class DispatcherService {
 public:
  explicit DispatcherService(
      std::shared_ptr<vehicle::VehicleService> vehicleService,
      std::shared_ptr<MapApplicationService> mapService,
      std::shared_ptr<infrastructure::services::CommonService> commonService);

  ~DispatcherService() = default;

  // ==================== AGV 调度 ====================

  /**
   * @brief 请求AGV导航到目标站点（只记录目标，不立即下发）
   * @details 参考三方代码 dispatcher.cpp:323-347 StationTaskFromServer
   *          和 dispatcher.cpp:432-460 AgvNavToStation
   *
   * @param agv AGV实体指针
   * @param targetStation 目标站点ID
   * @param floor 楼层
   * @param operation 到达后的操作（可选，用于MKLM的finalOperation）
   * @return 是否成功记录请求
   *
   * 工作流程：
   * 1. 设置 agv->setControlledByDispatcher(true)
   * 2. 记录导航请求到待规划队列
   * 3. 定时器会批量规划所有请求
   * 4. 规划完成后自动下发移动指令
   */
  bool requestNavigation(kernel::agv::AgvEntity* agv,
                         const std::string& targetStation, int floor,
                         const std::string& operation = "");

  void cancelPendingForAgv(int agvNumber);
  bool rescheduleAgvTask(int agvNumber);

  // ==================== 区域管理 ====================

  /**
   * @brief 检查区域冲突
   * @param station 站点ID
   * @param agvNumber AGV编号
   * @return 是否有冲突（true=有冲突，false=无冲突）
   */
  bool checkAreaConflict(const std::string& station, int agvNumber, int floor);

  /**
   * @brief 占用区域
   * @param station 站点ID
   * @param agvNumber AGV编号
   * @return 是否成功
   */
  bool occupyArea(const std::string& station, int agvNumber, int floor);

  /**
   * @brief 释放区域
   * @param station 站点ID
   * @param agvNumber AGV编号
   */
  void releaseArea(const std::string& station, int agvNumber, int floor);

  /**
   * @brief 释放AGV占用的所有区域（任务结束时调用）
   * @param agvNumber AGV编号
   */
  void releaseAllAreasForAgv(int agvNumber);

  // ==================== 状态查询 ====================

  /**
   * @brief 获取空闲AGV列表
   * @param floor 楼层（-1表示所有楼层）
   * @return AGV编号列表
   */
  void setDispatchCallback(std::function<void(int, const QList<QString>&)> cb);
  void setSolveFailureCallback(std::function<void(const QString&)> cb);
  std::vector<int> getIdleAgvs(int floor = -1);

  /**
   * @brief 根据目标站点与楼层选择最优空闲AGV（自动处理跨楼层）
   * @param targetStation 目标站点
   * @param floor 目标楼层
   * @param allowedTypes 允许的车型列表（空表示不限制）
   * @return AGV编号，-1 表示无可用车辆
   */
  int selectBestIdleAgv(const std::string& targetStation, int floor,
                        const std::vector<kernel::agv::AgvType>& allowedTypes = {});

  /**
   * @brief 检查AGV是否在指定楼层
   * @param agvNumber AGV编号
   * @param floor 楼层
   * @return 是否在该楼层
   */
  bool isAgvOnFloor(int agvNumber, int floor);

  /**
   * @brief 检查AGV是否正在充电
   * @param agvNumber AGV编号
   * @return 是否正在充电
   */
  bool isAgvCharging(int agvNumber);

  /**
   * @brief 自动选择泊车点：先同楼层按距离最近选择，再按楼层差距排序
   * @param agv 申请泊位的车辆
   * @param preferredFloor 当前/指定楼层（-1 表示使用 agv 当前楼层）
   * @return 可用泊车点，找不到时返回 nullptr
   */
  std::shared_ptr<park::ParkPoint> allocateParkingPoint(
      kernel::agv::AgvEntity* agv, int preferredFloor);

  /**
   * @brief 自动选择充电桩：先同楼层按距离最近选择，再按楼层差排序
   * @param agv 申请充电的车辆
   * @param preferredFloor 楼层（-1 表示使用 agv 当前楼层）
   * @return 可用充电桩，找不到时返回 nullptr
   */
  std::shared_ptr<charge::ChargePoint> allocateChargePoint(
      kernel::agv::AgvEntity* agv, int preferredFloor);

 private:
  std::shared_ptr<vehicle::VehicleService> m_vehicleService;
  std::shared_ptr<MapApplicationService> m_mapService;
  std::shared_ptr<kernel::ILogger> m_logger;
  std::shared_ptr<kernel::IConfiguration> m_config;

  // 多地图调度管理器（每个楼层一个RouteDispatcher）
  std::shared_ptr<DispatcherManager> m_dispatcherManager;

  /**
   * @brief 获取站点所在地图名称
   * @param floor 楼层
   * @return 地图名称
   */
  std::string getMapNameForFloor(int floor);

  /**
   * @brief 检查是否跨楼层
   * @param agvNumber AGV编号
   * @param targetFloor 目标楼层
   * @return 是否跨楼层
   */
  bool isCrossFloorTask(int agvNumber, int targetFloor);

  /**
   * @brief 计算AGV到站点的距离（简化版：欧氏距离）
   * @param agv AGV实体
   * @param targetStation 目标站点
   * @param floor 目标楼层
   * @return 距离
   */
  double calculateDistance(kernel::agv::AgvEntity* agv,
                           const std::string& targetStation,
                           int floor);
  /**
   * @brief 解析AGV当前所在楼层
   * @param agv AGV实体指针
   * @return 楼层编号
   */
  int resolveAgvFloor(const kernel::agv::AgvEntity* agv) const;

  /**
   * @brief 计算跨楼层电梯跳跃成本
   * @param fromFloor 起始楼层
   * @param targetFloor 目标楼层
   * @return 跳跃成本值
   */
  int calculateLiftHopCost(int fromFloor, int targetFloor) const;

  /**
   * @brief 尝试获取第三方区域（电梯/自动门等）
   * @param areaId 区域ID
   * @param agvNumber AGV编号
   * @param floor 楼层
   * @return 是否成功获取
   */
  bool tryAcquireThirdPartyArea(const QString& areaId,
                                int agvNumber,
                                int floor);

  /**
   * @brief 释放第三方区域（电梯/自动门等）
   * @param areaId 区域ID
   * @param agvNumber AGV编号
   * @param floor 楼层
   */
  void releaseThirdPartyArea(const QString& areaId,
                             int agvNumber,
                             int floor);
};

}  // namespace dispatcher
}  // namespace application
